#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<string.h>

#define NUM 30
#define SIZE 20
#define SEP " "

char s[NUM];            //s可以是全局变量，当作"内存"使用

int main()
{
    while(1)
    {
        printf("[root@localhost shell]#");          //此语句最后面不能加\n,否则会换行
        fflush(stdout);
        //char s[NUM];            //s不是存储char*的,在下面的while循环中只是用来存储字符串
        memset(s, '\0', sizeof s);//需要用memset对s进行初始化，否则s里面可能是随机值或者上次遗留下来的数据
        
        ////测试
        //int i = 0;
        //for(i = 0; i < NUM; ++i)
        //    printf("%c ", s[i]);
        
        fgets(s, sizeof s, stdin);       //此处不许加while循环，因为只进行一次
        if(strcmp(s, "\n") == 0)        //如果输入的只有换行符时，重新进入循环。比较的是\n而不是\0
            continue;
        s[strlen(s) - 1] = '\0';
        //printf("%s\n", s);
        
        char* _ele[SIZE] = { NULL };        //_ele不能加const修饰*_ele,否则与下方的execvp参数不符
        _ele[0] = strtok(s, SEP);        //SEP需要的是字符串而不是字符
        //printf("%s\n", _ele[0]);
        int index = 1;

        if(strcmp(_ele[0], "ll") == 0)
        {
            _ele[0] = (char*)"ls";
            _ele[index++] = (char*)"-l";
        }
        if(strcmp(_ele[0], "ls") == 0)
        {
            _ele[index++] = (char*)"--color=auto";
        }

        while(_ele[index++] = strtok(NULL, SEP));        
        ////测试
        //int i = 0;
        //for(i = 0; i < index; ++i)
        //    printf("_ele[%d] = %s\n", i, _ele[i]);
        
        //内建命令
        if(strcmp(_ele[0], "cd") == 0)
        {
            if(_ele[1] != NULL)         //最好加上这层判断
                chdir(_ele[1]);         //需要使用chdir而不是execvp,否则父进程执行完该指令后就直接退出了
            continue;
        }

        pid_t id = fork();
        if(id == 0)
        {
            printf("子进程执行代码\n");
            execvp(_ele[0], _ele);        //此处应该用v而不是用l，应该_ele是一个指针数组
            exit(1);            //加上这语句，当子进程切换进程失败时直接退出
        }
        int status = 0;
        pid_t res = waitpid(id, &status, 0);
        if(res > 0)     //加上这语句。当等待子进程成功时才执行输出语句
            printf("子进程退出码:%d\n", WEXITSTATUS(status));
    }

    return 0;
}
